Session Checker
A skill for checking if CircleTel customer PPPoE/RADIUS sessions are active using the Interstellio (NebularStack) Telemetry API. Analyzes CDR (Call Detail Records) to determine real-time connection status.
When This Skill Activates
This skill automatically activates when you:
- Need to check if a customer's internet session is active
- Want to view session history for a subscriber
- Debug connection issues or troubleshoot "not connected" complaints
- Analyze session patterns and terminate causes
- Check PPPoE connection status
Keywords: session active, session status, connection status, PPPoE session, check session, CDR records, subscriber online, is connected, client session, terminate cause
Core Concepts
Session States
| State | terminate_cause | Meaning |
|---|---|---|
| Active | null | Session is currently connected |
| Disconnected | Lost-Carrier | Connection lost (modem/router issue) |
| User Ended | User-Request | User initiated disconnect |
| Idle Timeout | Idle-Timeout | Session timed out due to inactivity |
| Session Timeout | Session-Timeout | Max session duration reached |
| Admin Disconnect | Admin-Reset | Administratively disconnected |
| Port Error | Port-Error | NAS/BNG port issue |
| NAS Error | NAS-Error | Network access server error |
CDR Record Fields
| Field | Description |
|---|---|
id | Unique session identifier |
start_time | When session started (ISO 8601) |
update_time | Last accounting update |
username | PPPoE username (e.g., customer@circletel.co.za) |
calling_station_id | Customer's IP address assigned by BRAS |
called_station_id | BRAS/BNG IP address |
nas_ip_address | NAS that authenticated the session |
duration | Session duration in seconds |
terminate_cause | Why session ended (null if active) |
Quick Check Methods
Method 1: Using the Interstellio Client (Programmatic)
typescript1import { getInterstellioClient } from '@/lib/interstellio' 2 3// Set token first (get from Interstellio dashboard or auth) 4const client = getInterstellioClient() 5client.setToken(process.env.INTERSTELLIO_API_TOKEN!, 'circletel.co.za') 6 7// Quick check - just returns true/false 8const isActive = await client.isSessionActive('subscriber-uuid-here') 9console.log('Session active:', isActive) 10 11// Detailed analysis 12const analysis = await client.analyzeSessionStatus('subscriber-uuid-here') 13console.log('Analysis:', { 14 isActive: analysis.isActive, 15 lastSession: analysis.lastSession?.username, 16 sessionsToday: analysis.totalSessionsToday, 17 terminateCauses: analysis.terminateCauses 18}) 19 20// Get raw CDR records for custom analysis 21const records = await client.getCDRRecords('subscriber-uuid', { 22 start_time: '2025-12-19T00:00:00+02:00', 23 end_time: '2025-12-19T23:59:59+02:00' 24})
Method 2: Using PowerShell (Quick CLI Check)
powershell1# Run the session checker script 2powershell -File .claude/skills/session-checker/check-session.ps1 -SubscriberId "23ffee86-dbe9-11f0-9102-61ef2f83e8d9"
Method 3: Direct API Call (cURL/PowerShell)
powershell1$headers = @{ 2 "X-Auth-Token" = $env:INTERSTELLIO_API_TOKEN 3 "X-Tenant-ID" = "circletel.co.za" 4 "X-Domain" = "circletel.co.za" 5 "X-Timezone" = "Africa/Johannesburg" 6 "Content-Type" = "application/json" 7} 8 9$body = @{ 10 start_time = (Get-Date).Date.ToString("yyyy-MM-ddT00:00:00+02:00") 11 end_time = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss+02:00") 12} | ConvertTo-Json 13 14$response = Invoke-RestMethod ` 15 -Uri "https://telemetry-za.nebularstack.com/v1/subscriber/{subscriber_id}/cdr/records" ` 16 -Method POST ` 17 -Headers $headers ` 18 -Body $body 19 20# Check if session is active 21if ($response.terminate_cause -eq $null) { 22 Write-Host "Session is ACTIVE" -ForegroundColor Green 23 Write-Host "Username: $($response.username)" 24 Write-Host "Connected since: $($response.start_time)" 25 Write-Host "Duration: $([math]::Round($response.duration / 60, 1)) minutes" 26} else { 27 Write-Host "Session is DISCONNECTED" -ForegroundColor Red 28 Write-Host "Last terminate cause: $($response.terminate_cause)" 29}
Finding Subscriber IDs
From Supabase (CircleTel Database)
sql1-- Find subscriber by customer email 2SELECT 3 cs.interstellio_subscriber_id, 4 cs.radius_username, 5 c.email, 6 c.first_name, 7 c.last_name 8FROM customer_services cs 9JOIN customers c ON cs.customer_id = c.id 10WHERE c.email = 'customer@example.com'; 11 12-- Find subscriber by account number 13SELECT 14 cs.interstellio_subscriber_id, 15 cs.radius_username, 16 cs.status 17FROM customer_services cs 18JOIN customers c ON cs.customer_id = c.id 19WHERE c.account_number = 'CT-2025-00001';
From Interstellio API
typescript1// Search by username 2const subscribers = await client.listSubscribers({ 3 username: 'customer@circletel.co.za' 4}) 5const subscriberId = subscribers.payload[0]?.id
Common Troubleshooting Scenarios
Scenario 1: Customer Reports "No Internet"
-
Check session status:
typescript1const analysis = await client.analyzeSessionStatus(subscriberId) -
Interpret results:
isActive: true→ Session is up, issue is elsewhere (DNS, routing, etc.)isActive: falsewithLost-Carrier→ Customer's router lost connectionisActive: falsewithSession-Timeout→ Session expired, needs reconnect
-
Check session history for patterns:
typescript1// Multiple Lost-Carrier in short time = unstable line 2if (analysis.terminateCauses['Lost-Carrier'] > 5) { 3 console.log('Line appears unstable - recommend technician check') 4}
Scenario 2: Checking Before Service Activation
typescript1// Ensure no orphaned sessions before provisioning 2const existingSessions = await client.listSessions(subscriberId) 3if (existingSessions.payload.length > 0) { 4 // Disconnect existing sessions first 5 await client.disconnectAllSessions(subscriberId) 6}
Scenario 3: Usage Monitoring Dashboard
typescript1// Get today's session stats for dashboard 2const analysis = await client.analyzeSessionStatus(subscriberId) 3 4const dashboardData = { 5 connectionStatus: analysis.isActive ? 'Online' : 'Offline', 6 currentSessionDuration: analysis.lastSession?.duration || 0, 7 reconnectsToday: analysis.terminateCauses['Lost-Carrier'] || 0, 8 totalOnlineTime: analysis.totalDurationSeconds 9}
API Reference
Endpoint
POST https://telemetry-za.nebularstack.com/v1/subscriber/{subscriber_id}/cdr/records
Required Headers
| Header | Value |
|---|---|
X-Auth-Token | JWT from Interstellio identity service |
X-Tenant-ID | circletel.co.za |
X-Domain | circletel.co.za |
X-Timezone | Africa/Johannesburg |
Content-Type | application/json |
Request Body
json1{ 2 "start_time": "2025-12-19T00:00:00+02:00", 3 "end_time": "2025-12-19T23:59:59+02:00" 4}
Note: Maximum query window is 32 days.
Response Example
json1{ 2 "id": "4d81f126-dcd1-11f0-9e13-a59eec990c99::2025-12-01", 3 "start_time": "2025-12-19T13:53:15.000+02:00", 4 "update_time": "2025-12-19T14:20:50.132+02:00", 5 "acct_unique_id": "4d81f126-dcd1-11f0-9e13-a59eec990c99", 6 "username": "customer@circletel.co.za", 7 "calling_station_id": "100.125.57.136", 8 "called_station_id": "100.127.1.229", 9 "nas_ip_address": "41.198.130.3", 10 "client_ip_address": "13.247.40.35", 11 "duration": 1655, 12 "terminate_cause": "Lost-Carrier" 13}
Environment Variables Required
env1INTERSTELLIO_API_TOKEN=your_jwt_token_here 2INTERSTELLIO_TENANT_ID=circletel.co.za 3INTERSTELLIO_DOMAIN=circletel.co.za
Related Files
| File | Purpose |
|---|---|
lib/interstellio/client.ts | Interstellio API client |
lib/interstellio/types.ts | TypeScript types including CDR records |
docs/api/INTERSTELLIO_API.md | Full API documentation |
.claude/skills/session-checker/check-session.ps1 | PowerShell quick-check script |
Best Practices
- Always check session status before disconnecting - Don't blindly disconnect active sessions
- Use timezone-aware dates - Always include
+02:00for South Africa - Handle empty results - API may return empty if no sessions in time window
- Cache tokens - Interstellio tokens are valid for 12 months
- Monitor terminate causes - High
Lost-Carriercounts indicate line issues
Version: 1.0.0 Last Updated: 2025-12-20 Maintained By: CircleTel Development Team API Source: https://docs.interstellio.io/